home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.6)
-
- '''
- '''
- __author__ = 'Robert Ancell <bob27@users.sourceforge.net>'
- __license__ = 'GNU General Public License Version 2'
- __copyright__ = 'Copyright 2005-2006 Robert Ancell'
- __all__ = [
- 'SANConverter']
- SAN_TAKE = 'x'
- SAN_CASTLE_SHORT = 'O-O'
- SAN_CASTLE_LONG = 'O-O-O'
- RANKS = 'abcdefgh'
- FILES = '12345678'
- SAN_PROMOTE = '='
-
- class Error(Exception):
- '''
- '''
- pass
-
-
- class SANConverter:
- '''
-
- Define file and rank
- '''
- WHITE = 'White'
- BLACK = 'Black'
- PAWN = 'P'
- KNIGHT = 'N'
- BISHOP = 'B'
- ROOK = 'R'
- QUEEN = 'Q'
- KING = 'K'
- __pieceTypes = PAWN + KNIGHT + BISHOP + ROOK + QUEEN + KING
- __promotionTypes = PAWN + KNIGHT + BISHOP + ROOK + QUEEN
- CHECK = '+'
- CHECKMATE = '#'
-
- def __init__(self):
- '''Constructor'''
- pass
-
-
- def getPiece(self, location):
- """Get a piece from the chess board.
-
- 'location' is the location to get the piece from (string, e.g. 'a1', h8').
-
- Return a tuple containing (colour, type) or None if no piece at this location.
- """
- pass
-
-
- def testMove(self, colour, start, end, promotionType, allowSuicide = False):
- """Test if a move is valid.
-
- 'colour' is the colour of the player making the move (self.WHITE or self.BLACK).
- 'start' is the board location to move from (string, e.g. 'a1', 'h8').
- 'end' is the board location to move to (string, e.g. 'a1', 'h8').
- 'promotionType' is the piece type to promote to (self.[PAWN|KNIGHT|BISHOP|ROOK|QUEEN]).
- 'allowSuicide' is a flag to show if the move should be disallowed (False) or
- allowed (True) if it would put the moving player into check.
-
- Return False if the move is dissallowed or
- self.CHECK if the move puts the opponent into check or
- self.CHECKMATE if the move puts the opponent into checkmate or
- True if the move is allowed and does not put the opponent into check.
- """
- pass
-
-
- def decode(self, colour, san):
- """Decode a SAN move.
-
- 'colour' is the colour of the player making the move (self.WHITE or self.BLACK).
- 'san' is the SAN description of the move (string).
-
- Returns the move this SAN describes in the form (start, end, promotionType).
- 'start' is the square to move from (string, e.g. 'a1', 'h8').
- 'end' is the square to move to (string, e.g. 'a1', 'h8').
- 'promotionType' is the piece to promote to (self.[KNIGHT|BISHOP|ROOK|QUEEN]).
- If the move is invalid then an Error expection is raised.
- """
- copy = san[:]
- expectedResult = True
- if copy[-1] == self.CHECK or copy[-1] == self.CHECKMATE:
- expectedResult = copy[-1]
- copy = copy[:-1]
-
- promotionType = self.QUEEN
- if copy[-2] == SAN_PROMOTE:
- promotionType = copy[-1]
- copy = copy[:-2]
- if self._SANConverter__promotionTypes.find(promotionType) < 0:
- raise Error("Error decoding '%s', Invalid promotion type %s" % (repr(san), repr(promotionType)))
- self._SANConverter__promotionTypes.find(promotionType) < 0
- elif self._SANConverter__promotionTypes.find(copy[-1]) >= 0:
- promotionType = copy[-1]
- copy = copy[:-1]
-
- if colour is self.WHITE:
- baseFile = '1'
- else:
- baseFile = '8'
- if copy == SAN_CASTLE_SHORT:
- return ('e' + baseFile, 'g' + baseFile, expectedResult, promotionType)
- if copy == SAN_CASTLE_LONG:
- return ('e' + baseFile, 'c' + baseFile, expectedResult, promotionType)
- end = copy[-2:]
- copy = copy[:-2]
- if RANKS.find(end[0]) < 0 or FILES.find(end[1]) < 0:
- raise Error("Error decoding '%s', Invalid destination type %s" % (repr(san), repr(end)))
- FILES.find(end[1]) < 0
- isTake = False
-
- try:
- if copy[-1] == SAN_TAKE:
- isTake = True
- copy = copy[:-1]
- except:
- copy == SAN_CASTLE_LONG
- copy == SAN_CASTLE_SHORT
-
- pieceType = self.PAWN
- rank = None
- if len(copy) > 0:
- if RANKS.find(copy[0]) >= 0:
- rank = copy[0]
- copy = copy[1:]
-
-
- file = None
- if len(copy) > 0:
- if FILES.find(copy[0]) >= 0:
- file = copy[0]
- copy = copy[1:]
-
-
- if len(copy) != 0:
- raise Error('Error decoding %s, Unexpected extra characters %s' % (repr(san), repr(end)))
- len(copy) != 0
- moveResult = None
- move = None
- if rank is not None and file is not None:
- start = rank + file
- moveResult = self.testMove(colour, start, end, promotionType = promotionType)
- move = (start, end)
- elif file is None:
- fileRange = FILES
- else:
- fileRange = file
- if rank is None:
- rankRange = RANKS
- else:
- rankRange = rank
- for file in fileRange:
- for rank in rankRange:
- start = rank + file
- piece = self.getPiece(start)
- if piece is None:
- continue
-
- if piece[0] != colour or piece[1] != pieceType:
- continue
-
- result = self.testMove(colour, start, end, promotionType = promotionType)
- if result is False:
- continue
-
- if moveResult is not None:
- raise Error('Error decoding %s, Move is ambiguous, at least %s and %s are possible' % (repr(san), repr(move), repr([
- start,
- end])))
- moveResult is not None
- moveResult = result
- move = [
- start,
- end]
-
-
- if moveResult is None:
- raise Error('Error decoding %s, Not a valid move' % repr(san))
- moveResult is None
- return (move[0], move[1], expectedResult, promotionType)
-
-
- def encode(self, start, end, isTake = False, promotionType = QUEEN):
- """Convert glChess co-ordinate move to SAN notation.
-
- 'start' is the square to move from (string, e.g. 'a1', 'h8').
- 'end' is the square to move to (string, e.g. 'a1', 'h8').
- 'promotionType' is the piece used for pawn promotion (if necessary).
-
- Return the move in SAN notation or None if unable to convert.
- """
- piece = self.getPiece(start)
- if piece is None:
- raise Error('Encode error, no piece to move at %s' % repr(start))
- piece is None
- (pieceColour, pieceType) = piece
- if self.testMove(pieceColour, start, end, promotionType) is False:
- raise Error('Encode error, move %s%s is invalid' % (start, end))
- self.testMove(pieceColour, start, end, promotionType) is False
- if pieceType is self.KING:
- if pieceColour is self.WHITE:
- baseFile = '1'
- else:
- baseFile = '8'
- shortCastle = ('e' + baseFile, 'g' + baseFile)
- longCastle = ('e' + baseFile, 'c' + baseFile)
- san = None
- if (start, end) == shortCastle:
- san = SAN_CASTLE_SHORT
- elif (start, end) == longCastle:
- san = SAN_CASTLE_LONG
-
- if san is not None:
- result = self.testMove(pieceColour, start, end, promotionType = promotionType, allowSuicide = True)
- if result is self.CHECK:
- san += self.CHECK
- elif result is self.CHECKMATE:
- san += self.CHECKMATE
-
- return san
-
- file = '?'
- rank = '?'
- if pieceType is self.PAWN and isTake:
- rank = start[0]
-
- result = self._SANConverter__isUnique(pieceColour, pieceType, rank + file, end, promotionType)
- if result is None:
- rank = start[0]
- file = '?'
- result = self._SANConverter__isUnique(pieceColour, pieceType, rank + '?', end, promotionType)
- if result is None:
- rank = '?'
- file = start[1]
- result = self._SANConverter__isUnique(pieceColour, pieceType, '?' + file, end, promotionType)
- if result is None:
- result = self._SANConverter__isUnique(pieceColour, pieceType, rank + file, end, promotionType)
- if result is None:
- raise Error('Encode error, unable to find unique move for %s%s' % (start, end))
- result is None
-
-
-
- san = ''
- if pieceType is not self.PAWN:
- san += pieceType
-
- if rank != '?':
- san += rank
-
- if file != '?':
- san += file
-
- if isTake:
- san += SAN_TAKE
-
- san += end
- if pieceColour is self.WHITE:
- promotionFile = '8'
- else:
- promotionFile = '1'
- if pieceType == self.PAWN and end[1] == promotionFile:
- san += SAN_PROMOTE + promotionType
-
- if result is self.CHECK:
- san += self.CHECK
- elif result is self.CHECKMATE:
- san += self.CHECKMATE
-
- return san
-
-
- def __isUnique(self, colour, pieceType, start, end, promotionType = QUEEN):
- """Test if a move is unique.
-
- 'colour' is the piece colour being moved. (self.WHITE or self.BLACK).
- 'pieceType' is the type of the piece being moved (self.[PAWN|KNIGHT|BISHOP|ROOK|QUEEN|KING]).
- 'start' is the start location of the move (tuple (file, rank). rank and file can be None).
- 'end' is the end point of the move (tuple (file,rank)).
- 'promotionType' is the piece type to promote pawns to (self.[PAWN|KNIGHT|BISHOP|ROOK|QUEEN]).
-
- Return the result of self.testMove() if a unique move is found otherwise None.
- """
- lastResult = None
- if start[0] == '?':
- rankRange = RANKS
- else:
- rankRange = start[0]
- if start[1] == '?':
- fileRange = FILES
- else:
- fileRange = start[1]
- for file in fileRange:
- for rank in rankRange:
- p = self.getPiece(rank + file)
- if p is None:
- continue
-
- if p[1] != pieceType or p[0] != colour:
- continue
-
- result = self.testMove(colour, rank + file, end, promotionType = promotionType, allowSuicide = True)
- if result is not False:
- if lastResult != None:
- return None
- lastResult = result
- continue
- lastResult != None
-
-
- return lastResult
-
-
- if __name__ == '__main__':
- import chess_board
-
- class TestConverter(SANConverter):
- '''
- '''
- __colourToSAN = {
- chess_board.WHITE: SANConverter.WHITE,
- chess_board.BLACK: SANConverter.BLACK }
- __sanToColour = { }
- for a, b in __colourToSAN.iteritems():
- __sanToColour[b] = a
-
- __typeToSAN = {
- chess_board.PAWN: SANConverter.PAWN,
- chess_board.KNIGHT: SANConverter.KNIGHT,
- chess_board.BISHOP: SANConverter.BISHOP,
- chess_board.ROOK: SANConverter.ROOK,
- chess_board.QUEEN: SANConverter.QUEEN,
- chess_board.KING: SANConverter.KING }
- __sanToType = { }
- for a, b in __typeToSAN.iteritems():
- __sanToType[b] = a
-
- __board = None
-
- def __init__(self, board):
- self._TestConverter__board = board
-
-
- def testEncode(self, start, end):
- print str((start, end)) + ' => ' + str(self.encode(start, end))
-
-
- def testDecode(self, colour, san):
-
- try:
- result = self.decode(colour, san)
- print san.ljust(7) + ' => ' + str(result)
- except Error:
- e = None
- print san.ljust(7) + ' !! ' + str(e)
-
-
-
- def getPiece(self, file, rank):
- '''Called by SANConverter'''
- piece = self._TestConverter__board.getPiece((file, rank))
- if piece is None:
- return None
- return (self._TestConverter__colourToSAN[piece.getColour()], self._TestConverter__typeToSAN[piece.getType()])
-
-
- def testMove(self, colour, start, end, promotionType, allowSuicide = False):
- '''Called by SANConverter'''
- moveResult = self._TestConverter__board.testMove(self._TestConverter__sanToColour[colour], (start, end), self._TestConverter__sanToType[promotionType], allowSuicide)
- return {
- chess_board.MOVE_RESULT_ILLEGAL: False,
- chess_board.MOVE_RESULT_ALLOWED: True,
- chess_board.MOVE_RESULT_OPPONENT_CHECK: self.CHECK,
- chess_board.MOVE_RESULT_OPPONENT_CHECKMATE: self.CHECKMATE }[moveResult]
-
-
- b = chess_board.ChessBoard()
- c = TestConverter(b)
- print b
- c.testEncode((1, 1), (1, 2))
- c.testEncode((1, 0), (2, 2))
- c.testDecode(c.WHITE, 'c3')
- c.testDecode(c.WHITE, 'Pc3')
- c.testDecode(c.WHITE, 'c4')
- c.testDecode(c.WHITE, 'Nc3')
- c.testDecode(c.WHITE, 'Qd3')
- c.testDecode(c.WHITE, 'Qd3=X')
- c.testDecode(c.WHITE, 'x3')
- c.testDecode(c.WHITE, 'ic3')
- print b
-
-